#include "person.h"
#include "building.h"   // We needs to do this to avoid a circular declaration problem
#include "levelscene.h"


Person::Person(PathMap *mapper, QPixmap personPixmap, LevelScene *parent, QGraphicsScene *scene)
    : QGraphicsPixmapItem(personPixmap)
{
    scene->addItem(this);
    setData(ITEM_TYPE,GameItems::Person);

    setOffset(-(pixmap().width()/2),-(pixmap().height()/2));

    //randomly decide if this person is sick for now
    if (rand()%2)
        virus = 0;
    else
        virus = new Virus((rand()%1000),(rand()%1000),(rand()%1000),(rand()%1000),(rand()%1000),this);

    // Create the stats object for the person
    stats = new PersonStats();

    currentBuilding = 0;

    pathMap = mapper;
    pathLocation = 0;

    parentScene = parent;

    inBuilding = true;
    setVisible(false);

}

void Person::timerEvent(QTimerEvent *)
{
    killTimer(timerID);
    Building * oldBuilding;
    oldBuilding = currentBuilding;

    int newBuildingID = (rand() % parentScene->buildings.length());
    while (oldBuilding == parentScene->buildings.at(newBuildingID))
        newBuildingID = (rand() % parentScene->buildings.length());

    currentBuilding = parentScene->buildings.at(newBuildingID);
    parentScene->setBuilding(this, currentBuilding);
    emit solvePath(oldBuilding->getEnterencePoint(),currentBuilding->getEnterencePoint(),this);
    setVisible(true);
    inBuilding = false;
}

void Person::startPerson()
{
    if (inBuilding)
        timerID = startTimer(rand() % 30000);
}

void Person::stopPerson()
{
    if (inBuilding)
        killTimer(timerID);
}

void Person::treatPerson()
{
    //Something will eventually happen here
}

void Person::advance(int phase)
{
    if (phase == 0)
    {
        // catch collisions

        QList<QGraphicsItem*> collisionList = collidingItems();

        Person * collidingPerson;

        // run through all the colliding items to see if any are important
        for (int index = 0; index < collisionList.length(); index++)
        {
            // see if this item is a sprite or background
            if (collisionList.at(index)->data(ITEM_TYPE) == GameItems::Person)
            {
                collidingPerson = (Person*)collisionList.at(index);
                collidesWithPerson(collidingPerson);
            }
        }

        //Move person along path
        if (path.size() > 0)
        {
            if ((unsigned int)(pathLocation + 1) < path.size())
            {
                int prevX, prevY, nextX, nextY;
                double localMovement;

                pathMap->StateToXY(path.at((int)pathLocation), prevX, prevY);
                pathMap->StateToXY(path.at((int)pathLocation + 1), nextX, nextY);
                localMovement = pathLocation - (int)pathLocation;

                double moveX, moveY;
                moveX = localMovement * (nextX - prevX);
                moveY = localMovement * (nextY - prevY);

                setPos((moveX + prevX) * 20, (moveY + prevY) * 20);
                pathLocation += 0.125;
            }

            if (pathLocation > path.size()-2)
                arrive();
        }
    }
}

void Person::collidesWithPerson(Person *colliding)
{
    //Transmit the virus
    if(virus != 0 && colliding->virus == 0 && (rand() % 100) * 10 + virus->Infectivity + stats->Contagiousness > 1000)
    {
        colliding->virus = new Virus(virus->Virulence, virus->Infectivity, virus->DrugResistance, virus->ImmuneResistance, virus->Hp, this);
    }
    else if(colliding->virus != 0 && virus == 0 && (rand() % 100) * 10 + colliding->virus->Infectivity + stats->Contagiousness >= 1000)
    {
        virus = new Virus(colliding->virus->Virulence, colliding->virus->Infectivity, colliding->virus->Infectivity, colliding->virus->ImmuneResistance, colliding->virus->Hp, this);
    }
}

Building * Person::getCurrentBuilding()
{
    return currentBuilding;
}

void Person::setCurrentBuilding(Building *newBuilding)
{
    currentBuilding = newBuilding;
}

bool Person::isInBuilding()
{
    return inBuilding;
}

void Person::setPath(std::vector<void *>newPath)
{
    path = newPath;
}

void Person::arrive()
{
    setVisible(false);
    inBuilding = true;
    pathLocation = 0;
    path.clear();
    timerID = startTimer(20000 + ((rand() % 16000)-8000));
}
